package com.example.graduatetest.view.model;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.graphics.Color;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.EditText;
import android.widget.RadioGroup;
import android.widget.TextView;
import android.widget.Toast;

import androidx.appcompat.widget.Toolbar;
import androidx.lifecycle.MediatorLiveData;
import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.ViewModel;

import com.baidu.geofence.GeoFence;
import com.baidu.geofence.GeoFenceClient;
import com.baidu.geofence.GeoFenceListener;
import com.baidu.geofence.model.DPoint;
import com.baidu.location.BDAbstractLocationListener;
import com.baidu.location.BDLocation;
import com.baidu.location.LocationClient;
import com.baidu.location.LocationClientOption;
import com.baidu.mapapi.map.BaiduMap;
import com.baidu.mapapi.map.BitmapDescriptorFactory;
import com.baidu.mapapi.map.CircleOptions;
import com.baidu.mapapi.map.MapPoi;
import com.baidu.mapapi.map.MapStatus;
import com.baidu.mapapi.map.MapStatusUpdate;
import com.baidu.mapapi.map.MapStatusUpdateFactory;
import com.baidu.mapapi.map.MapView;
import com.baidu.mapapi.map.Marker;
import com.baidu.mapapi.map.MarkerOptions;
import com.baidu.mapapi.map.MyLocationData;
import com.baidu.mapapi.map.PolygonOptions;
import com.baidu.mapapi.map.Stroke;
import com.baidu.mapapi.model.LatLng;
import com.baidu.mapapi.model.LatLngBounds;
import com.example.graduatetest.R;
import com.example.graduatetest.bean.Card;
import com.example.graduatetest.callback.CardCallBack;
import com.example.graduatetest.callback.StringCallBack;
import com.example.graduatetest.databinding.ActivityFindCardBinding;
import com.example.graduatetest.model.CardModel;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

public class FindCardViewModel extends ViewModel implements GeoFenceListener {
    private Activity activity;
    private ActivityFindCardBinding binding;
    private Card cardNow;
    private Handler handlerUi = new Handler();
    private MutableLiveData<String> buttonText;
    private MutableLiveData<String> class_number;
    private boolean isIn = false;
    private String cardResult = "出勤";



    public void init(Activity activity, ActivityFindCardBinding binding,String class_id) {
        this.activity = activity;
        this.binding = binding;
        toolbarInit();
        if(buttonText == null) buttonText = new MediatorLiveData<>();
        if(class_number == null){
            class_number = new MutableLiveData<>();
            if(!class_id.equals("NULL")){
                class_number.setValue(class_id);
            }
        }
        buttonText.setValue("查询");
        init();
        initClick();
    }

    //toolbar初始化
    private void toolbarInit() {
        Toolbar toolbar = binding.toolbar7;
        toolbar.setTitle("打卡");
        toolbar.setNavigationIcon(R.drawable.ic_arrow_back_black_24dp);
        toolbar.setNavigationOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //注销广播
                activity.unregisterReceiver(mGeoFenceReceiver);
                activity.onBackPressed();
            }
        });
    }

    public MutableLiveData<String> getButtonText() {
        return buttonText;
    }

    public MutableLiveData<String> getClass_number() {
        return class_number;
    }

    /**
     * 用于显示当前的位置
     * 示例中是为了显示当前的位置，在实际使用中，单独的地理围栏可以不使用定位接口
     */
    private LocationClient mlocationClient;
    private MapView mMapView;
    private BaiduMap mBdMap;
    // 中心点坐标
    private LatLng centerLatLng;
    // 多边形围栏的边界点
    private List<LatLng> polygonPoints = new ArrayList<>();
    private List<Marker> markerList = new ArrayList<>();
    // 当前的坐标点集合，主要用于进行地图的可视区域的缩放
    private LatLngBounds.Builder boundsBuilder = new LatLngBounds.Builder();
    // 中心点marker
    private Marker centerMarker;
    private MarkerOptions markerOption = null;
    // 地理围栏客户端
    private GeoFenceClient fenceClient = null;
    // 要创建的围栏半径
    private float fenceRadius;
    // 触发地理围栏的行为，默认为进入提醒
    private int activatesAction = GeoFenceClient.GEOFENCE_IN;
    // 地理围栏的广播action
    private static final String GEOFENCE_BROADCAST_ACTION = "com.example.graduatetest";

    // 记录已经添加成功的围栏
    private HashMap<String, GeoFence> fenceMap = new HashMap<>();



    //初始化地图相关
    private void init() {

        mMapView = binding.mapView;

        fenceClient = new GeoFenceClient(activity.getApplicationContext());
        markerOption = new MarkerOptions().draggable(true);
        mlocationClient = new LocationClient(activity.getApplicationContext());
        LocationClientOption option = new LocationClientOption();
        option.setOpenGps(true); // 使用gps定位
        option.setCoorType(GeoFenceClient.BD09LL); // 设置坐标类型
        option.setScanSpan(1000);

        // 设置locationClientOption
        mlocationClient.setLocOption(option);

        // 注册LocationListener监听器
        MyLocationListener myLocationListener = new MyLocationListener();
        mlocationClient.registerLocationListener(myLocationListener);
        mlocationClient.start();


        if (mBdMap == null) {
            mBdMap = mMapView.getMap();
            mBdMap.setMyLocationEnabled(true);
            mBdMap.getUiSettings().setRotateGesturesEnabled(false);
        }

        IntentFilter filter = new IntentFilter();
        filter.addAction(GEOFENCE_BROADCAST_ACTION);
        activity.registerReceiver(mGeoFenceReceiver, filter);
        /**
         * 创建pendingIntent
         */
        fenceClient.createPendingIntent(GEOFENCE_BROADCAST_ACTION);
        // 在即将触发侦听行为时允许开启高精度定位模式(开启gps定位，gps定位结果优先)
        fenceClient.isHighAccuracyLoc(true);
        fenceClient.setGeoFenceListener(this);
        /**
         * 设置地理围栏的触发行为,默认为进入
         */
        fenceClient.setActivateAction(GeoFenceClient.GEOFENCE_IN);


        MapStatus.Builder builder = new MapStatus.Builder();
        builder.target(centerLatLng)//缩放中心点
                .zoom(18);//缩放级别
        mBdMap.animateMapStatus(MapStatusUpdateFactory
                .newMapStatus(builder.build()));
    }

    //设置点击事件
    private void initClick(){
        binding.btPunchCard.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                String class_number = binding.edClassNumber.getText().toString();
                String code = binding.edCode.getText().toString();

                if(buttonText.getValue().equals("查询")){
                    CardModel.getOneCard(class_number, code, new CardCallBack() {
                        @Override
                        public void onSuccess(final Card card) {

                            handlerUi.post(new Runnable() {
                                @Override
                                public void run() {
                                    cardNow = card;
                                    addRoundFence(card.getLat(),card.getLon(),card.getSet_meter());
                                }
                            });
                        }

                        @Override
                        public void onFailed() {
                            Log.e("haha", "获取失败");
                        }
                    });
                }else{

                    SharedPreferences preferences = activity.getSharedPreferences("data", Context.MODE_PRIVATE);
                    String number = preferences.getString("number", "2017211973");
                    //在范围内
                    if(isIn){
                        if(cardNow.getStatus().equals("正在考勤")){
                            cardResult = "出勤";
                        }else{
                            cardResult = "迟到";
                        }
                        CardModel.punchCard(number, class_number, code, cardResult, new StringCallBack() {
                            @Override
                            public void onSuccess(String result) {
                                if(result.equals("success")){
                                    handlerUi.post(new Runnable() {
                                        @Override
                                        public void run() {
                                            Toast.makeText(activity, "打卡成功", Toast.LENGTH_SHORT).show();
                                            activity.onBackPressed();
                                        }
                                    });
                                    //解除广播
                                    activity.unregisterReceiver(mGeoFenceReceiver);
                                }
                            }

                            @Override
                            public void onFailed() {
                                Log.e("haha", "打卡失败");
                            }
                        });
                    }else{
                        Toast.makeText(activity, "未在区域内", Toast.LENGTH_SHORT).show();
                    }

                }

            }
        });
    }


    private void drawFence(GeoFence fence) {
        switch (fence.getType()) {
            case GeoFence.TYPE_ROUND:
                drawCircle(fence, false);
                break;
            case GeoFence.TYPE_BDMAPPOI:
                drawCircle(fence, true);
                break;
            case GeoFence.TYPE_POLYGON:
//			case GeoFence.TYPE_DISTRICT :
                drawPolygon(fence);
                break;
            default:
                break;
        }

        // 设置所有maker显示在当前可视区域地图中
        LatLngBounds bounds = boundsBuilder.build();
        MapStatusUpdate mapStatusUpdate = MapStatusUpdateFactory.newLatLngBounds(bounds, 50,
                50, 50, 50);
        // 更新地图状态
        mBdMap.animateMapStatus(mapStatusUpdate);
        removeMarkers();
    }

    /**
     * 绘制圆
     */
    private void drawCircle(GeoFence fence, boolean isPoi) {
        LatLng center;
        int radius;
        if (isPoi) {
            BDLocation bdLocation = new BDLocation();
            bdLocation.setLatitude(fence.getCenter().getLatitude());
            bdLocation.setLongitude(fence.getCenter().getLongitude());
            BDLocation tempLocation = LocationClient
                    .getBDLocationInCoorType(bdLocation, BDLocation.BDLOCATION_GCJ02_TO_BD09LL);
            center = new LatLng(tempLocation.getLatitude(),
                    tempLocation.getLongitude());
        } else {
            center = centerLatLng;
        }
        radius = (int) fence.getRadius();
        // 绘制一个圆形
        if (center == null) {
            return;
        }
        mBdMap.addOverlay(new CircleOptions().center(center)
                .radius(radius)
                .fillColor(0x666495ED) // 填充颜色
                .stroke(new Stroke(3, 0xE66495ED)));
        boundsBuilder.include(center);

        if (!isPoi) {
            centerLatLng = null;
        }
    }

    /**
     *  绘制Polygon
     */
    private void drawPolygon(GeoFence fence) {
        final List<DPoint> pointList = fence.getPoints();
        if (null == pointList || pointList.isEmpty()) {
            return;
        }
        List<LatLng> lst = new ArrayList<>();

        for (DPoint point : pointList) {
            lst.add(new LatLng(point.getLatitude(), point.getLongitude()));
            boundsBuilder.include(
                    new LatLng(point.getLatitude(), point.getLongitude()));
        }
        mBdMap.addOverlay(new PolygonOptions()
                .points(polygonPoints)
                .fillColor(0x666495ED) // 填充颜色
                .stroke(new Stroke(5, 0xE66495ED)));

        if (polygonPoints != null && polygonPoints.size() > 0) {
            polygonPoints.clear();
        }

    }

    Object lock = new Object();

    void drawFence2Map() {
        new Thread() {
            @Override
            public void run() {
                try {
                    synchronized (lock) {
                        if (null == fenceList || fenceList.isEmpty()) {
                            return;
                        }
                        for (GeoFence fence : fenceList) {
                            if (fenceMap.containsKey(fence.getFenceId())) {
                                continue;
                            }
                            drawFence(fence);
                            fenceMap.put(fence.getFenceId(), fence);
                        }
                    }
                } catch (Throwable e) {
                    e.printStackTrace();
                }
            }
        }.start();
    }

    @SuppressLint("HandlerLeak")
    private Handler handler = new Handler() {
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case 0:
                    StringBuffer sb = new StringBuffer();
                    sb.append("添加围栏成功  ");
                    String customId = (String) msg.obj;
                    if (!TextUtils.isEmpty(customId)) {
                        sb.append(" 业务ID: ").append(customId);
                    }
                    Log.e("haha",sb.toString());
                    drawFence2Map();
                    break;
                case 1:
                    int errorCode = msg.arg1;
                    Log.e("haha","添加围栏失败,ErrorCode = " + errorCode);
                    break;
                case 2:
                    String statusStr = (String) msg.obj;
                    Log.e("haha","JJ:"+statusStr);
                    break;
                default:
                    break;
            }
        }
    };

    List<GeoFence> fenceList = new ArrayList<>();

    @Override
    public void onGeoFenceCreateFinished(final List<GeoFence> geoFenceList,
                                         int errorCode, String customId) {
        Message msg = Message.obtain();
        if (errorCode == GeoFence.ADDGEOFENCE_SUCCESS) {
            fenceList.addAll(geoFenceList);
            msg.obj = customId;
            msg.what = 0;
        } else {
            msg.arg1 = errorCode;
            msg.what = 1;
        }
        handler.sendMessage(msg);
    }



    /**
     * 接收触发围栏后的广播,当添加围栏成功之后，会立即对所有围栏状态进行一次侦测，只会发送一次围栏和位置之间的初始状态；
     * 当触发围栏之后也会收到广播,对于同一触发行为只会发送一次广播不会重复发送，除非位置和围栏的关系再次发生了改变。
     */
    private BroadcastReceiver mGeoFenceReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            // 接收广播
            if (intent.getAction().equals(GEOFENCE_BROADCAST_ACTION)) {
                Bundle bundle = intent.getExtras();
                String customId = bundle
                        .getString(GeoFence.BUNDLE_KEY_CUSTOMID);
                String fenceId = bundle.getString(GeoFence.BUNDLE_KEY_FENCEID);
                GeoFence geoFence = bundle.getParcelable(GeoFence.BUNDLE_KEY_FENCE);
                int status = bundle.getInt(GeoFence.BUNDLE_KEY_FENCESTATUS);
                int locType = bundle.getInt(GeoFence.BUNDLE_KEY_LOCERRORCODE);
                StringBuffer sb = new StringBuffer();
                switch (status) {
                    case GeoFence.INIT_STATUS_IN:
                        sb.append("围栏初始状态:在围栏内");
                        isIn = true;
                        break;
                    case GeoFence.INIT_STATUS_OUT:
                        sb.append("围栏初始状态:在围栏外");
                        isIn = false;
                        break;
                    case GeoFence.STATUS_LOCFAIL:
                        sb.append("定位失败,无法判定目标当前位置和围栏之间的状态");
                        isIn = false;
                        break;
                    case GeoFence.STATUS_IN:
                        sb.append("进入围栏");
                        isIn = true;
                        break;
                    case GeoFence.STATUS_OUT:
                        sb.append("离开围栏 ");
                        isIn = true;
                        break;
                    case GeoFence.STATUS_STAYED:
                        sb.append("在围栏内停留超过10分钟 ");
                        isIn = true;
                        break;
                    default:
                        break;
                }

                String str = sb.toString();
                Message msg = Message.obtain();
                msg.obj = str;
                msg.what = 2;
                handler.sendMessage(msg);
            }
        }
    };

    private void addCenterMarker(LatLng latlng) {
        if (null == centerMarker) {
            centerMarker = (Marker) mBdMap.addOverlay(new MarkerOptions().position(latlng).icon(BitmapDescriptorFactory
                    .fromResource(R.drawable.class_info)));
        }
        centerMarker.setPosition(latlng);
        centerMarker.setVisible(true);
        markerList.add(centerMarker);
    }


    private void removeMarkers() {
        if (null != centerMarker) {
            centerMarker.remove();
            centerMarker = null;
        }
        if (null != markerList && markerList.size() > 0) {
            for (Marker marker : markerList) {
                marker.remove();
            }
            markerList.clear();
        }
    }


    /**
     * 添加圆形围栏
     */
    private void addRoundFence(double lat,double lon,int r) {
        centerLatLng = new LatLng(lat, lon);
        fenceRadius = (float)r;
        DPoint centerPoint = new DPoint(lat,lon);
        fenceClient.addGeoFence(centerPoint, GeoFenceClient.BD09LL, fenceRadius, "001");
        buttonText.setValue("打卡");
    }





    public class MyLocationListener extends BDAbstractLocationListener {
        @Override
        public void onReceiveLocation(BDLocation location) {
            // mapView 销毁后不在处理新接收的位置
            if (location == null || mMapView == null) {
                return;
            }
            MyLocationData locData = new MyLocationData.Builder()
                    // 此处设置开发者获取到的方向信息，顺时针0-360
                    .direction(location.getDirection())
                    .latitude(location.getLatitude())
                    .longitude(location.getLongitude())
                    .build();

            mBdMap.setMyLocationData(locData);
        }
    }
}